在過去的幾天裡,我們從經典的 FizzBuzz 到充滿挑戰的字串計算機,我們親手、完整地走過了數次 TDD 的「紅-綠-重構」循環,我們看到了程式碼如何在測試的驅動下一步步「演進」出來,也感受到了那張由測試所帶來的巨大信心。
我們已經完成了本系列最核心的「弄髒手體會」階段,在我們迎接AI介入TDD之前,我們有必要停下腳步,喝口涼的,回顧一下這段旅程,並解答一些核心的疑惑。
今天的目標:不寫任何程式碼,而是進行一次深度的復盤與問答,我們到底從手動 TDD Kata 中學到了什麼?
在字串計算機 Kata 中,每當我們新增一個功能或進行一次重構,我們都會立即執行 go test
,那一片綠燈 就是我們的最大安全感——信心。
現在,如果你想知道 stringcalc.Add
函式的所有功能,你應該先看 stringcalc_test.go
,這份文件永遠與程式碼的實際行為保持同步。
這是我在推廣 TDD 或任何測試實踐時,幾乎 70% 會聽到的反駁。這句話聽起來很有道理,因為截止日期(Deadline)永遠在那裡,但透過 Kata 的實踐,我們可以對這個問題有更深刻的回答。
讓我們回顧一下傳統的開發流程:
寫程式 -> 手動測試 -> 發現 Bug -> 設定斷點 -> 反覆猜測 -> 修改 -> 再手動測試 ...
在這個流程中, 「Debug」 和 「手動回歸測試」 是一個巨大的時間黑洞。你花了多少個深夜,用 fmt.Println
或 console.log
來記錄一個變數的變化?你花了多少時間,在Deploy前,手動點遍應用的所有按鈕,祈禱沒有弄壞任何東西?
而 TDD 的流程則是:
寫一個失敗的測試 -> 寫剛好能通過的程式碼 -> 重構 -> 執行所有測試 ...
TDD 並沒有消除寫程式碼的時間,而是做了一次時間投資的轉移,它預先支付了一部分時間來編寫自動化測試,用以大幅削減後期無盡的除錯和手動回歸測試的時間。
TDD 是一種紀律,它強迫我們放慢腳步去思考,最終卻能讓我們更快地到達終點。
TDD 不是關於“寫得快”,而是關於“持續快”。
下一次當你覺得“沒時間寫測試”時,不妨問問自己:“我真的有那麼多時間,可以浪費在未來無盡的Debug 或是 手動整合測試上嗎?”
在我們的 Kata 中,我們嚴格遵守了一個原則:測試 Add 函式時,我們沒有依賴任何外部系統,如資料庫、API 或檔案系統。我們寫的這種測試,就是最純粹的單元測試 (Unit Test)。
理解不同層級的測試至關重要:
這三者構成了「測試金字塔」。單元測試是基石,數量應該最多,因為它們運行速度快,能提供最即時的反饋。TDD 主要就是聚焦在金字塔的這一層。
在享受 TDD 帶來的好處的同時,我們也必須誠實地承認,在某些環節,這個過程可能略顯繁瑣:
這些「痛點」都類似於 重複性的工作、窮舉式的思考,恰恰好這都是 AI 最擅長解決的問題!
今天,我們進行了一次寶貴的沉澱,我們總結了 TDD 的核心價值,還正面回應了 「沒時間」 這一經典迷思,並清晰地劃分了不同測試層級的界線。
針對 “沒有時間寫單元測試“ 這點可以拜讀隔壁棚 Kuma 哥的系列文: 你就是都不寫測試才會沒時間:Kuma 的 30 天 Unit Test 手把手教學,從理論到實戰 (Java 篇)
預告:第三階段正式開啟!Day 16 - 何時不該用 TDD?誠實面對其限制與權衡
雖然我們花了這麼多天在學習和實踐 TDD,但現實很現實,我們不能只談好處而迴避限制,明天,我們將誠實地探討:
只有誠實面對 TDD 的限制,我們才能更好地理解何時使用它。